package com.rex.saas.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.rex.saas.bean.*;
import com.rex.saas.bean.request.*;
import com.rex.saas.bean.response.*;
import com.rex.saas.constants.ApiConstant;
import com.rex.saas.constants.Constants;
import com.rex.saas.db.entity.*;
import com.rex.saas.db.mapper.*;
import com.rex.saas.enums.DeviceTypeEnum;
import com.rex.saas.enums.GwStatusEnum;
import com.rex.saas.utils.JwtUtils;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName DeviceService
 * @Description:
 * @Author: zhusiyu
 * @CreateDate: 2024/12/18 11:06	//创建时间
 */
@Component
@Slf4j
public class DeviceService {

    @Autowired
    RexolarApiClient rexolarApiClient;

    @Autowired
    AssetService assetService;

    @Autowired
    TslModelService tslModelService;

    @Autowired
    SaasDeviceInfoMapper saasDeviceInfoMapper;

    @Autowired
    SaasSpaceDeviceRelationMapper saasSpaceDeviceRelationMapper;

    @Autowired
    SaasGatewayDevicePositionMapper saasSpaceDevicePositionMapper;

    @Autowired
    PaasGatewayDeviceRelationMapper paasGatewayDeviceRelationMapper;

    @Autowired
    PaasGatewayCredentialsMapper paasGatewayCredentialsMapper;

    @Autowired
    SaasDeviceEventMapper saasDeviceEventMapper;

    @Autowired
    SaasDeviceLogMapper saasDeviceLogMapper;

    @Autowired
    SaasSpaceInfoMapper saasSpaceInfoMapper;

    @Autowired
    SaasUserInfoMapper saasUserInfoMapper;

    @Autowired
    SaasDeviceLabelRelationMapper saasDeviceLabelRelationMapper;

    @Autowired
    SaasSpaceLabelMapper saasSpaceLabelMapper;

    @Autowired
    SaasDeviceLabelMapper saasDeviceLabelMapper;

    private static final Cache<String, Integer> gwStatusCache = Caffeine.newBuilder()
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .maximumSize(1000)
            .build();

    private static final Cache<String, String> deviceGwRelationCache = Caffeine.newBuilder()
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .maximumSize(1000)
            .build();


    private static final long ONLINE_MILLISECOND = 10 * 60 * 1000;

    @Getter
    private static Map<String, String> modelMap = new HashMap<>();
    private static Map<String, Integer> modelOnlineMap = new HashMap<>();

    static {
        modelMap.put("HY0141", "鸿雁一键单火开关");
        modelMap.put("HY0142", "鸿雁二键单火开关");
        modelMap.put("HY0143", "鸿雁三键单火开关");
        modelMap.put("QYL008", "人体存在");
        modelMap.put("LF0053", "嵌入式16A插座（10A）");
        modelMap.put("TS011F", "计量空开 （速通）");
        modelMap.put("TS0601", "计量空开");
        modelMap.put("RG5310", "吸顶网关");
        modelMap.put("RT0103", "三键单火开关");
        modelMap.put("QYL001", "门磁");
        modelMap.put("QYL002", "水浸");
        modelMap.put("QYL003", "紧急按钮");
        modelMap.put("QYL004", "温湿度计");
        modelMap.put("QYL005", "烟感");
        modelMap.put("QYL007", "PIR");
        modelMap.put("HomY001", "空调网关 （M08）");
        modelMap.put("RT0101", "一键单火开关");
        modelMap.put("LF0049", "空调面板");
        modelMap.put("LF0019", "拉菲三合一温控");
        modelMap.put("WR0023", "红外转发");
        modelMap.put("RH0070", "64路空调网关");
        modelMap.put("UNDEFINED", "未定义");

        modelOnlineMap.put("QYL001", 60 * 60 * 1000);
        modelOnlineMap.put("QYL002", 60 * 60 * 1000);
        modelOnlineMap.put("QYL003", 60 * 60 * 1000);
        modelOnlineMap.put("QYL007", 60 * 60 * 1000);
        modelOnlineMap.put("QYL004", 120 * 60 * 1000);
        modelOnlineMap.put("QYL005", 60 * 60 * 1000);

    }

    public CtDeviceDetailResponse ctDetail(DeviceBasicData deviceBasicData, String tenantToken) {
        CtDeviceDetailResponse response = new CtDeviceDetailResponse();
        String deviceId = deviceBasicData.getCoreId();
        response.setCoreId(deviceBasicData.getCoreId());
        response.setType(DeviceTypeEnum.DEVICE.getCode());
        response.setDeviceName(deviceBasicData.getName());
        response.setDeviceAlias(deviceBasicData.getLabel());
        response.setCategoryId(deviceBasicData.getProfileId());
        String profileName = "";
        Map<String, String> deviceProfiles = rexolarApiClient.getDeviceProfiles(tenantToken);
        if (deviceProfiles != null && deviceProfiles.get(deviceBasicData.getProfileId()) != null) {
            profileName = deviceProfiles.get(deviceBasicData.getProfileId());
        }
        response.setCategoryName(profileName);
        Map<String, List<DeviceTimeSeries>> deviceTimeSeriesMap = rexolarApiClient.getDeviceTimeSeriesLatest(
                deviceId, tenantToken, new String[]{Constants.TotalCEE_1, Constants.TotalCEI_1}, false);
        for (String key : deviceTimeSeriesMap.keySet()) {
            List<DeviceTimeSeries> values = deviceTimeSeriesMap.get(key);
            JSONObject jsonObject = JSONObject.parseObject(values.get(0).toJSONString());
            if (Constants.TotalCEI_1.equals(key)) {
                response.setImportEnergy(jsonObject.getString("value"));
            } else if (Constants.TotalCEE_1.equals(key)) {
                response.setExportEnergy(jsonObject.getString("value"));
            }
        }
        Map<String, Object> deviceAttributes = rexolarApiClient.getDeviceAttributes(deviceId, tenantToken,
                new String[]{Constants.LAST_ACTIVITY_TIME, Constants.ACTIVE, Constants.SWBuildID, Constants.ModelId_1, Constants.ModelId, Constants.WiFi0});
        if (deviceAttributes != null) {
            response.setLastUpdateTime(deviceAttributes.get(Constants.LAST_ACTIVITY_TIME) == null ? 0 : Long.parseLong(deviceAttributes.get(Constants.LAST_ACTIVITY_TIME).toString()));
            String modelId = null;
            if (deviceAttributes.get(Constants.ModelId) != null) {
                modelId = deviceAttributes.get(Constants.ModelId).toString();
//            } else if (deviceAttributes.get(Constants.ModelId_1) != null) {
//                modelId = deviceAttributes.get(Constants.ModelId_1).toString();
            } else {
                modelId = "UNDEFINED";
            }
            response.setModelId(modelId);
            response.setModelName(modelMap.get(modelId));

            Integer status = deviceAttributes.get(Constants.ACTIVE)==null?0:deviceAttributes.get(Constants.ACTIVE).toString().equals("true")?1:0;
            response.setStatus(status);
            response.setVersion(deviceAttributes.get(Constants.Version) == null ? "" : deviceAttributes.get(Constants.Version).toString());
            response.setSWBuildID(deviceAttributes.get(Constants.SWBuildID) == null ? "" : deviceAttributes.get(Constants.SWBuildID).toString());
            if (deviceAttributes.get(Constants.WiFi0) != null){
                Map jsonObject = (Map) deviceAttributes.get(Constants.WiFi0);
                if (jsonObject!= null) response.setWifiRssi(jsonObject.get(Constants.RSSI) == null ? null :Integer.parseInt(jsonObject.get(Constants.RSSI).toString()));
            }
        }

        List<SaasSpaceDeviceRelation> spaces = saasSpaceDeviceRelationMapper.selectList(new LambdaQueryWrapper<SaasSpaceDeviceRelation>()
                .eq(SaasSpaceDeviceRelation::getDeviceName, deviceBasicData.getName()));
        if (!CollectionUtils.isEmpty(spaces)) {
            response.setSpaceId(spaces.get(0).getSpaceInfoId());
            SaasSpaceInfo spaceInfo = saasSpaceInfoMapper.selectById(spaces.get(0).getSpaceInfoId());
            if (spaceInfo == null) {
                log.error("ctDetail spaceInfo is null, spaceInfoId:{}", spaces.get(0).getSpaceInfoId());
            }
            response.setSpaceName(spaceInfo.getName());
        }

        List<SaasDeviceLabelRelation> devcieLabels = saasDeviceLabelRelationMapper.selectList(new LambdaQueryWrapper<SaasDeviceLabelRelation>()
                .eq(SaasDeviceLabelRelation::getDeviceName, deviceBasicData.getName()));
        if (!CollectionUtils.isEmpty(devcieLabels)) {
            SaasDeviceLabelRelation label = devcieLabels.get(0);
            SaasDeviceLabel saasDeviceLabel = saasDeviceLabelMapper.selectById(label.getLabelId());
            if (saasDeviceLabel != null) {
                response.setDeviceLabel(saasDeviceLabel.getLabelName());
                response.setDeviceLabelIconUrl(saasDeviceLabel.getIconUrl());
            }
            SaasSpaceLabel spaceLabel = saasSpaceLabelMapper.selectById(label.getSpaceLabelId());
            if (spaceLabel != null) {
                response.setSpaceLabel(spaceLabel.getLabelName());
                response.setSpaceLabelIconUrl(spaceLabel.getIconUrl());
            }
        }
        return response;
    }

    public DeviceDetailResponse detail(DeviceBasicData deviceBasicData, String token) {
        DeviceDetailResponse response = new DeviceDetailResponse();
        String tenantId = JwtUtils.getTenantId(token);
        response.setDeviceId(deviceBasicData.getCoreId());
        response.setDeviceName(deviceBasicData.getName());
        response.setDeviceAlias(deviceBasicData.getLabel());
        response.setCategoryId(deviceBasicData.getProfileId());
        List<SaasSpaceDeviceRelation> list = assetService.getAssetByDevice(tenantId, deviceBasicData.getName());
        if (!CollectionUtils.isEmpty(list)) {
            response.setSpaceId(list.get(0).getSpaceId());
            AssetBasicData assetBasicData = rexolarApiClient.getAssetById(list.get(0).getSpaceId(), token);
            if (assetBasicData != null) {
                response.setSpaceName(assetBasicData.getLabel());
            }
        }
        String profileName = "";
        Map<String, String> deviceProfiles = rexolarApiClient.getDeviceProfiles(token);
        if (deviceProfiles != null && deviceProfiles.get(deviceBasicData.getProfileId()) != null) {
            profileName = deviceProfiles.get(deviceBasicData.getProfileId());
        }
        response.setCategoryId(profileName);
        if (profileName != null) {
            response.setCategoryName(profileName);
            if ("default".equals(profileName)) {
                response.setNodeType("device");
            } else {
                response.setNodeType("gateway");
            }
        }
        String deviceId = deviceBasicData.getCoreId();
        if ("gateway".equals(response.getNodeType())) {
            List<DeviceDetailResponse> subDeviceResponses = new ArrayList<>();
            List<DeviceBasicData> subDevices = rexolarApiClient.getToRelationsInfo(token, deviceId, "DEVICE");
            for (DeviceBasicData subDevice : subDevices) {
                if (subDevice.getCoreId().equals(deviceId)) {
                    continue;
                }
                DeviceBasicData tmp = rexolarApiClient.getDeviceById(subDevice.getCoreId(), token);
                DeviceDetailResponse subDeviceResponse = detail(tmp, token);
                if (subDeviceResponse == null){
                    log.error("detail subDeviceResponse is null, gwName:{}", subDevice.getName());
                    continue;
                }
                DeviceBasicData subDeviceDetail = rexolarApiClient.getDeviceByDeviceName(subDevice.getName(), token);
                if (subDeviceDetail != null) {
                    subDeviceResponse.setDeviceAlias(subDeviceDetail.getLabel());
                }
                subDeviceResponses.add(subDeviceResponse);
            }
            response.setSubDevicesList(subDeviceResponses);
        }

        Map<String, List<DeviceTimeSeries>> deviceTimeSeriesMap = rexolarApiClient.getDeviceTimeSeriesLatest(deviceId, token, new String[]{}, false);
        List<TimeSeries> timeSeries = new ArrayList<>();
        long ts = 0;
        if(!CollectionUtils.isEmpty(deviceTimeSeriesMap)){
            for (String key : deviceTimeSeriesMap.keySet()) {
                TimeSeries map = new TimeSeries();
                List<DeviceTimeSeries> values = deviceTimeSeriesMap.get(key);
                JSONObject jsonObject = JSONObject.parseObject(values.get(0).toJSONString());
                map.setValue(jsonObject.getString("value"));
                map.setKey(key);
                Long tmpTs = jsonObject.getLong("ts");
                map.setTs(tmpTs);
                if (tmpTs > ts) {
                    ts = tmpTs;
                }
                timeSeries.add(map);
            }
            response.setLastUpdateTime(ts);
            response.setLatestTimeSeries(timeSeries);
        }

        Map<String, Object> deviceAttributes = rexolarApiClient.getDeviceAttributes(deviceId, token,
                new String[]{Constants.LAST_ACTIVITY_TIME, Constants.ACTIVE, Constants.VERSION, Constants.ModelId_1, Constants.ModelId, Constants.POWER, Constants.Status,
                        Constants.SubDevices, Constants.RSSI, Constants.Version, Constants.joinNetTime, Constants.devStatus,Constants.SWBuildID, Constants.WiFi0});
        if (deviceAttributes != null) {
            response.setStatus("true".equals(deviceAttributes.get(Constants.ACTIVE).toString()) ? 1 : 0);
            String modelId = "";
            if (deviceAttributes.get(Constants.ModelId) != null) {
                modelId = deviceAttributes.get(Constants.ModelId).toString();
            }
            if("default".equals(response.getCategoryName())){
                response.setCategoryName(modelMap.get(modelId));
            }
            response.setStatus(getDeivceStatus(deviceAttributes, deviceBasicData.getCoreId(), response.getNodeType(), token));
            response.setSubDevices(deviceAttributes.get(Constants.SubDevices) == null ? "" : deviceAttributes.get(Constants.SubDevices).toString());
            response.setVersion(deviceAttributes.get(Constants.Version) == null ? "" : deviceAttributes.get(Constants.Version).toString());

            response.setModelId(modelId);
            response.setRssi(deviceAttributes.get(Constants.RSSI) == null ? "" : deviceAttributes.get(Constants.RSSI).toString());
            response.setVersion(deviceAttributes.get(Constants.Version) == null ? "" : deviceAttributes.get(Constants.Version).toString());
            response.setSWBuildID(deviceAttributes.get(Constants.SWBuildID) == null ? "" : deviceAttributes.get(Constants.SWBuildID).toString());
            response.setJoinNetTime(deviceAttributes.get(Constants.joinNetTime) == null ? null : Long.parseLong(deviceAttributes.get(Constants.joinNetTime).toString()));
            response.setModelName(modelMap.get(modelId));
            response.setPower(deviceAttributes.get(Constants.POWER) == null ? 0 : (Integer) deviceAttributes.get(Constants.POWER));
            if (deviceAttributes.get(Constants.WiFi0) != null){
                Map jsonObject = (Map) deviceAttributes.get(Constants.WiFi0);
                if (jsonObject != null) response.setWifiRssi(jsonObject.get(Constants.RSSI) == null ? null :Integer.parseInt(jsonObject.get(Constants.RSSI).toString()));
            }
//            if(response.getLastUpdateTime()==0){
//                if(deviceAttributes.get(Constants.LAST_ACTIVITY_TIME)==null){
//                    log.warn("deviceTimeSeriesMap is null, deviceName:{}", deviceBasicData.getName());
//                }else {
//                    response.setLastUpdateTime((Long) deviceAttributes.get(Constants.LAST_ACTIVITY_TIME));
//                }
//            }
        }

        return response;

    }

    public DeviceTimeSeriesResponse timeSeries(DeviceTimeSeriesRequest deviceTimeSeriesRequest, String token, Long startTime, Long endTime, String coreId) {
        DeviceTimeSeriesResponse deviceTimeSeriesResponse = new DeviceTimeSeriesResponse();
        BeanUtils.copyProperties(deviceTimeSeriesRequest, deviceTimeSeriesResponse);
        Map<String, Object> deviceTimeSeriesMap = rexolarApiClient.getDeviceTimeSeries(
                coreId, token, new String[]{deviceTimeSeriesRequest.getKey()}
                , startTime, endTime, 100000, false, null, null, false);
        if (CollectionUtils.isEmpty(deviceTimeSeriesMap)) {
            return deviceTimeSeriesResponse;
        }
        List<Map> deviceTimeSeries = (List<Map>) deviceTimeSeriesMap.get(deviceTimeSeriesRequest.getKey());
        Set<Long> tsSet = new HashSet<>();
        List<Map> result = new ArrayList<>();
        for (Map timeSeries : deviceTimeSeries){
            Long ts = (Long) timeSeries.get("ts");
            if(tsSet.contains(ts)){
                continue;
            }
            tsSet.add(ts);
            result.add(timeSeries);
        }
        deviceTimeSeriesResponse.setDeviceTimeSeriesList(result);
        return deviceTimeSeriesResponse;
    }

    public List<DeviceLatestTimeSeriesResponse> latestTimeSeries(DeviceBasicData deviceBasicData, String token, List<String> keys) {
        List<DeviceLatestTimeSeriesResponse> responseList = new ArrayList<>();
        Map<String, List<DeviceTimeSeries>> timeSeriesLatest = rexolarApiClient.getDeviceTimeSeriesLatest(deviceBasicData.getCoreId(), token, keys.toArray(new String[0]), false);
        if (CollectionUtils.isEmpty(timeSeriesLatest)) {
            log.warn("getDeviceTimeSeriesLatest is empty, deviceName:{}, keys:{}", deviceBasicData.getName(), keys);
            return responseList;
        }
        for (String key : timeSeriesLatest.keySet()) {
            DeviceLatestTimeSeriesResponse response = new DeviceLatestTimeSeriesResponse();
            response.setKey(key);
            response.setTs((Long) timeSeriesLatest.get(key).get(0).get("ts"));
            response.setValue((String) timeSeriesLatest.get(key).get(0).get("value"));
            responseList.add(response);
        }
        return responseList;
    }

    public boolean permitAllJoin(PermitAllJoinRequest permitAllJoinRequest, String token, String gwId) {
        HashMap dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", permitAllJoinRequest.getDeviceName() + "-" + time);
        dataMap.put("DeviceId", permitAllJoinRequest.getDeviceName());
        dataMap.put("FunctionCode", "PermitAllJoin");
        HashMap payload = new HashMap();
        payload.put("Duration", permitAllJoinRequest.getDuration());
        dataMap.put("Payload", payload);
        return rexolarApiClient.updateDeviceAttributes(gwId, ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);

    }

    public boolean unbindSubDevice(UnbindSubDeviceRequest unbindSubDeviceRequest, String token, String gwId) {
        String tenantId = JwtUtils.getTenantId(token);
        HashMap dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", unbindSubDeviceRequest.getDeviceName() + "-" + time);
        dataMap.put("DeviceId", unbindSubDeviceRequest.getDeviceName());
        dataMap.put("FunctionCode", "DeleteDev");
        HashMap payload = new HashMap();
        JSONArray unbindSubDeviceList = new JSONArray();
        unbindSubDeviceList.addAll(unbindSubDeviceRequest.getSubDeviceNameList());
        payload.put("DeviceIds", unbindSubDeviceList);
        dataMap.put("Payload", payload);
        boolean gwFlag = rexolarApiClient.updateDeviceAttributes(gwId, ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
        if (!gwFlag) {
            log.error("unbindSubDevice updateDeviceAttributes error, deviceName:{}", unbindSubDeviceRequest.getDeviceName());
            return false;
        }
        for (String deviceName : unbindSubDeviceRequest.getSubDeviceNameList()) {
            DeviceBasicData subDeviceBasicData = rexolarApiClient.getDeviceByDeviceName(deviceName, token);
            if (subDeviceBasicData != null) {
                boolean subFlag = rexolarApiClient.deleteRelationsInfo(token, gwId, "DEVICE", "Created", subDeviceBasicData.getCoreId(), "DEVICE");
                if (!subFlag) {
                    log.error("unbindSubDevice deleteRelationsInfo error, deviceName:{}", unbindSubDeviceRequest.getDeviceName());
                }
            }
            boolean deleteFlag = rexolarApiClient.deleteDevice(subDeviceBasicData.getCoreId(), token);
            if (!deleteFlag) {
                log.error("unbindSubDevice deleteDevice error, deviceName:{}", unbindSubDeviceRequest.getDeviceName());
            }
            assetService.deleteDevice(tenantId, deviceName);
        }
        return true;
    }

    public boolean readLightDeviceProperty(DeviceBasicData deviceBasicData, String token, String property) {
        HashMap dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", deviceBasicData.getName() + "-" + time);
        dataMap.put("deviceId", deviceBasicData.getName());
        dataMap.put("property", property);
        dataMap.put("FunctionCode", "ReadLightDeviceProperty");
        return rexolarApiClient.updateDeviceAttributes(deviceBasicData.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
    }

    public boolean readDevProperty(DeviceBasicData deviceBasicData, String token, String property) {
        List<DeviceBasicData> gws = rexolarApiClient.getFromRelationsInfo(token, deviceBasicData.getCoreId());
        if (CollectionUtils.isEmpty(gws)) {
            log.error("readDevProperty gws is empty, deviceId:{}", deviceBasicData.getCoreId());
            return false;
        }

        HashMap dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", deviceBasicData.getCoreId() + "-" + time);
        dataMap.put("DeviceId", gws.get(0).getName());
        dataMap.put("FunctionCode", "ReadDevProperty");
        HashMap payload = new HashMap();
        payload.put("DeviceId", deviceBasicData.getName());
        payload.put("GroupId", "0");
        payload.put("Read", property);
        dataMap.put("Payload", payload);
        return rexolarApiClient.updateDeviceAttributes(gws.get(0).getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
    }

    public boolean updateAttributes(DeviceBasicData deviceBasicData, String token, String property, String value) {
        HashMap dataMap = new HashMap();
        dataMap.put(property, value);
        return rexolarApiClient.updateDeviceAttributes(deviceBasicData.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
    }

    public boolean writeLightDevProperty(DeviceBasicData deviceBasicData, String token, WriteDevPropertyRequest writeDevPropertyRequest) {
        HashMap dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", deviceBasicData.getName() + "-" + time);
        dataMap.put("deviceId", deviceBasicData.getName());
        dataMap.put("property", writeDevPropertyRequest.getProperty());
        dataMap.put("value", writeDevPropertyRequest.getValue());
        dataMap.put("FunctionCode", "WriteLightDevProperty");
        return rexolarApiClient.updateDeviceAttributes(deviceBasicData.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
    }

    public boolean writeDevProperty(DeviceBasicData deviceBasicData, String token, WriteDevPropertyRequest writeDevPropertyRequest) {
        List<DeviceBasicData> gws = rexolarApiClient.getFromRelationsInfo(token, deviceBasicData.getCoreId());
        if (CollectionUtils.isEmpty(gws)) {
            log.error("writeDevProperty gws is empty, deviceId:{}", deviceBasicData.getCoreId());
            return false;
        }
        HashMap dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", deviceBasicData.getCoreId() + "-" + time);
        dataMap.put("DeviceId", gws.get(0).getName());
        dataMap.put("FunctionCode", "WriteDevProperty");
        HashMap payload = new HashMap();
        payload.put("DeviceId", deviceBasicData.getName());
        payload.put("GroupId", writeDevPropertyRequest.getGroupId());
        payload.put("Write", writeDevPropertyRequest.getProperty());
        payload.put("Value", writeDevPropertyRequest.getValue());
        dataMap.put("Payload", payload);
        return rexolarApiClient.updateDeviceAttributes(gws.get(0).getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
    }


    public boolean invokeDevCommand(DeviceBasicData deviceBasicData, String token, InvokeDevCommandRequest invokeDevCommandRequest) {
        List<DeviceBasicData> gws = rexolarApiClient.getFromRelationsInfo(token, deviceBasicData.getCoreId());
        if (CollectionUtils.isEmpty(gws)) {
            log.error("invokeDevCommand gws is empty, deviceId:{}", deviceBasicData.getCoreId());
            return false;
        }
        HashMap dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", deviceBasicData.getCoreId() + "-" + time);
        dataMap.put("DeviceId", gws.get(0).getName());
        dataMap.put("FunctionCode", "InvokeDevCommand");
        HashMap payload = new HashMap();
        payload.put("DeviceId", deviceBasicData.getName());
        payload.put("GroupId", invokeDevCommandRequest.getGroupId());
        payload.put("Invoke", invokeDevCommandRequest.getInvoke());
        dataMap.put("Payload", payload);
        return rexolarApiClient.updateDeviceAttributes(gws.get(0).getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
    }

    public DeviceAtrributesResponse attributes(DeviceBasicData deviceBasicData, DeviceAttributesRequest deviceAttributesRequest, String token) {
        DeviceAtrributesResponse deviceAtrributesResponse = new DeviceAtrributesResponse();
        Map<String, Object> attributes = rexolarApiClient.getDeviceAttributes(deviceBasicData.getCoreId(),
                token, deviceAttributesRequest.getKeys().toArray(new String[deviceAttributesRequest.getKeys().size()]));
        if (CollectionUtils.isEmpty(attributes)) {
            log.warn("device attributes is empty, deviceId:{}", deviceAttributesRequest.getDeviceName());
            return deviceAtrributesResponse;
        }
        List<DeviceAttributesData> deviceAttributesDataList = new ArrayList<>();
        for (String key : attributes.keySet()) {
            DeviceAttributesData deviceAttributesData = new DeviceAttributesData();
            deviceAttributesData.setKey(key);
            deviceAttributesData.setValue(attributes.get(key));
            deviceAttributesDataList.add(deviceAttributesData);
        }
        deviceAtrributesResponse.setDeviceAttributesDataList(deviceAttributesDataList);
        return deviceAtrributesResponse;
    }
    public IPage<DeviceResponse> listPage(DeviceListRequest deviceListRequest, String token) {
        Page<DeviceResponse> page = new Page<>(deviceListRequest.getPageNo(), deviceListRequest.getPageSize());
        String tenantId = JwtUtils.getTenantId(token);
        List<DeviceResponse> responseList = new ArrayList<>();
        List<String> deviceNameList = new ArrayList<>();
        if (!StringUtils.isEmpty(deviceListRequest.getSpaceId())) {
            List<SaasSpaceDeviceRelation> relations = saasSpaceDeviceRelationMapper.selectList(new LambdaQueryWrapper<SaasSpaceDeviceRelation>().eq(SaasSpaceDeviceRelation::getSpaceId, deviceListRequest.getSpaceId()));
            if (CollectionUtils.isEmpty(relations)) {
                log.warn("listPage relations is empty, spaceId:{}", deviceListRequest.getSpaceId());
                return page;
            }
            deviceNameList = relations.stream().map(SaasSpaceDeviceRelation::getDeviceName).collect(Collectors.toList());
        }
        LambdaQueryWrapper<SaasDeviceInfo> queryWrapper = new LambdaQueryWrapper<SaasDeviceInfo>();
        queryWrapper.eq(SaasDeviceInfo::getTenantId, tenantId);
        queryWrapper.eq(SaasDeviceInfo::getCategoryId, deviceListRequest.getCategoryId());
        if(!StringUtils.isEmpty(deviceListRequest.getDeviceName())){
            queryWrapper.like(SaasDeviceInfo::getDeviceName, deviceListRequest.getDeviceName());
        }
        if(!CollectionUtils.isEmpty(deviceNameList)){
            queryWrapper.in(SaasDeviceInfo::getDeviceName, deviceListRequest.getDeviceName());
        }
        Page<SaasDeviceInfo> devicePage = new Page<>(deviceListRequest.getPageNo(), deviceListRequest.getPageSize());
        devicePage = saasDeviceInfoMapper.selectPage(devicePage, queryWrapper);
        for (SaasDeviceInfo saasDeviceInfo : devicePage.getRecords()) {
            DeviceResponse deviceResponse = getDeviceResponse(saasDeviceInfo, token);
            List<SaasSpaceDeviceRelation> assetList = assetService.getAssetByDevice(tenantId, saasDeviceInfo.getDeviceName());
            if (!CollectionUtils.isEmpty(assetList)) {
                SaasSpaceDeviceRelation asset = assetList.get(0);
                deviceResponse.setSpaceId(asset.getSpaceId());
                AssetBasicData assetBasicData = rexolarApiClient.getAssetById(asset.getSpaceId(), token);
                if (assetBasicData != null) {
                    deviceResponse.setSpaceName(assetBasicData.getLabel());
                }
            }
            responseList.add(deviceResponse);
        }
        BeanUtils.copyProperties(devicePage, page);
        page.setRecords(responseList);
        return page;
    }

    public List<DeviceResponse> list(String spaceId, String token) {
        List<DeviceResponse> responseList = new ArrayList<>();
        String tenantId = JwtUtils.getTenantId(token);
        if (!StringUtils.isEmpty(spaceId)) {
            List<SaasSpaceDeviceRelation> deviceList = assetService.getDeviceList(tenantId, spaceId);
            if (CollectionUtils.isEmpty(deviceList)) {
                log.warn("device list is empty, spaceInfoId:{}", spaceId);
                return responseList;
            }
            for (SaasSpaceDeviceRelation saasSpaceDeviceRelation : deviceList) {
                DeviceBasicData deviceBasicData = rexolarApiClient.getDeviceByDeviceName(saasSpaceDeviceRelation.getDeviceName(), token);
                if (deviceBasicData == null) {
                    log.warn("device is empty, deviceName:{}", saasSpaceDeviceRelation.getDeviceName());
                    continue;
                }
                DeviceResponse deviceResponse = getDeviceResponse(deviceBasicData, token);
                responseList.add(deviceResponse);
            }
        } else {
            List<DeviceBasicData> deviceBasicDataList = rexolarApiClient.getDeviceList(token);
            for (DeviceBasicData deviceBasicData : deviceBasicDataList) {
                DeviceResponse deviceResponse = getDeviceResponse(deviceBasicData, token);
                List<SaasSpaceDeviceRelation> assetList = assetService.getAssetByDevice(tenantId, deviceBasicData.getName());
                if (!CollectionUtils.isEmpty(assetList)) {
                    SaasSpaceDeviceRelation asset = assetList.get(0);
                    deviceResponse.setSpaceId(asset.getSpaceId());
                    AssetBasicData assetBasicData = rexolarApiClient.getAssetById(asset.getSpaceId(), token);
                    if (assetBasicData != null) {
                        deviceResponse.setSpaceName(assetBasicData.getLabel());
                    }
                }
                responseList.add(deviceResponse);
            }
        }
        return responseList;
    }
    public Page<DeviceResponse> listV2(DeviceListRequest deviceListRequest, String token) {
        Page<DeviceResponse> response = new Page<>();
        LambdaQueryWrapper<SaasSpaceDeviceRelation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SaasSpaceDeviceRelation::getSpaceInfoId, deviceListRequest.getSpaceId());
        if(!StringUtils.isEmpty(deviceListRequest.getCategoryId())){
            queryWrapper.eq(SaasSpaceDeviceRelation::getCategoryId, deviceListRequest.getCategoryId());
        }
        if(!CollectionUtils.isEmpty(deviceListRequest.getProductKeys())){
            queryWrapper.in(SaasSpaceDeviceRelation::getProductKey, deviceListRequest.getProductKeys());
        }
        Page<SaasSpaceDeviceRelation> page = new Page<>(deviceListRequest.getPageNo(), deviceListRequest.getPageSize());
        page = saasSpaceDeviceRelationMapper.selectPage(page, queryWrapper);
        BeanUtils.copyProperties(page, response);
        List<DeviceResponse> responseList = new ArrayList<>();
        for (SaasSpaceDeviceRelation relation : page.getRecords()){
            SaasDeviceInfo deviceInfo = saasDeviceInfoMapper.selectById(relation.getSpaceInfoId());
            if (deviceInfo == null){
                log.error("deviceInfo is null, DeviceInfo:{}", relation.getDeviceName());
                continue;
            }
            DeviceResponse deviceResponse = new DeviceResponse();
            deviceResponse.setId(deviceInfo.getId());
            deviceResponse.setDeviceId(deviceInfo.getCoreId());
            deviceResponse.setDeviceName(deviceInfo.getDeviceName());
            deviceResponse.setDeviceAlias(deviceInfo.getDeviceAlias());
            deviceResponse.setPosition(relation.getPosition());
            deviceResponse.setCategoryId(deviceInfo.getCategoryId());
            deviceResponse.setCategoryName(deviceInfo.getCategoryName());
            deviceResponse.setNodeType(DeviceTypeEnum.getMessageByCode(deviceInfo.getType()));
            deviceResponse.setGmtCreated(deviceInfo.getGmtCreated().getTime());
            deviceResponse.setStatus(0);
            if(Constants.DEFAULT.equals(deviceInfo.getCategoryName())){
                Map<String, Object> attributes = rexolarApiClient.getDeviceAttributes(deviceInfo.getCoreId(),  token, new String[]{Constants.DEV_STATUS});
                if (!CollectionUtils.isEmpty( attributes)){
                    deviceResponse.setStatus((Integer) attributes.get(Constants.DEV_STATUS));
                }
            }else {
                Map<String, Object> attributes = rexolarApiClient.getDeviceAttributes(deviceInfo.getCoreId(),  token, new String[]{Constants.ACTIVE});
                if (!CollectionUtils.isEmpty( attributes)){
                    deviceResponse.setStatus("true".equals(attributes.get(Constants.DEV_STATUS).toString())?1:0);
                }
            }
            responseList.add(deviceResponse);
        }
        response.setRecords(responseList);
        return response;
    }

    private DeviceResponse getDeviceResponse(DeviceBasicData deviceBasicData, String token) {
        DeviceResponse deviceResponse = new DeviceResponse();
        deviceResponse.setDeviceId(deviceBasicData.getCoreId());
        deviceResponse.setDeviceName(deviceBasicData.getName());
        deviceResponse.setDeviceAlias(deviceBasicData.getLabel());
        deviceResponse.setCategoryId(deviceBasicData.getProfileId());
        Map<String, String> deviceProfiles = rexolarApiClient.getDeviceProfiles(token);
        if (deviceProfiles != null && deviceProfiles.get(deviceBasicData.getProfileId()) != null) {
            deviceResponse.setCategoryName(deviceProfiles.get(deviceBasicData.getProfileId()) == null ? "" : deviceProfiles.get(deviceBasicData.getProfileId()));
        }
//        if (deviceResponse.getCategoryName().contains("网关") || Constants.GW_ZIGBEE.equals(deviceResponse.getCategoryName())) {
//            deviceResponse.setNodeType("gateway");
//        } else {
//            deviceResponse.setNodeType("device");
//        }
        if ("default".equals(deviceResponse.getCategoryName())) {
            deviceResponse.setNodeType("device");
        } else {
            deviceResponse.setNodeType("gateway");
        }
        Map<String, Object> deviceAttributes = rexolarApiClient.getDeviceAttributes(deviceBasicData.getCoreId(), token,
                new String[]{Constants.LAST_ACTIVITY_TIME, Constants.ACTIVE, Constants.Version, Constants.ModelId, "power", Constants.DEV_STATUS, Constants.RSSI, "IPAddress", "zigbeeChannel"});
        if (deviceAttributes != null) {
            String modelId = deviceAttributes.get(Constants.ModelId) == null ? "UNDEFINED" : deviceAttributes.get(Constants.ModelId).toString();
            String ipAddress = deviceAttributes.get("IPAddress") == null ? "" : deviceAttributes.get("IPAddress").toString();
            String zigbeeChannel = deviceAttributes.get("zigbeeChannel") == null ? "" : deviceAttributes.get("zigbeeChannel").toString();
            String modelName = modelMap.get(modelId);
            if(StringUtils.isEmpty(modelName)){
                log.warn("modelName is null, modelId:{}", modelId);
                modelName = "UNDEFINED";
            }
            if("default".equals(deviceResponse.getCategoryName())){
                deviceResponse.setCategoryName(modelName);
            }
            deviceResponse.setStatus(getDeivceStatus(deviceAttributes, deviceBasicData.getCoreId(), deviceResponse.getNodeType(), token));
            deviceResponse.setModelId(modelId);
            deviceResponse.setIpAddress(ipAddress);
            deviceResponse.setZigbeeChannel(zigbeeChannel);
            deviceResponse.setModelName(modelMap.get(modelId));
        }

        Map<String, List<DeviceTimeSeries>> deviceTimeSeriesMap = rexolarApiClient
                .getDeviceTimeSeriesLatest(deviceBasicData.getCoreId(), token, new String[]{}, false);
        long ts = 0;
        for (String key : deviceTimeSeriesMap.keySet()) {
            Map<String, String> map = new HashMap<>();
            List<DeviceTimeSeries> values = deviceTimeSeriesMap.get(key);
            JSONObject jsonObject = JSONObject.parseObject(values.get(0).toJSONString());
            map.put("value", jsonObject.getString("value"));
            map.put("key", key);
            Long tmpTs = jsonObject.getLong("ts");
            if (tmpTs > ts) {
                ts = tmpTs;
            }
            if(Constants.RSSI.equals(key)){
                deviceResponse.setRssi(jsonObject.getString("value"));
            }
        }
        deviceResponse.setLastUpdateTime(ts);
        if(deviceResponse.getLastUpdateTime()==0){
            if(deviceAttributes.get(Constants.LAST_ACTIVITY_TIME)==null){
                log.warn("getDeviceResponse deviceTimeSeriesMap is null, deviceName:{}", deviceBasicData.getName());
            }else {
                deviceResponse.setLastUpdateTime((Long) deviceAttributes.get(Constants.LAST_ACTIVITY_TIME));
            }
        }
        return deviceResponse;
    }

    public DeviceResponse getDeviceResponse(SaasDeviceInfo saasDeviceInfo, String token) {
        DeviceResponse deviceResponse = new DeviceResponse();
        deviceResponse.setDeviceId(saasDeviceInfo.getCoreId());
        deviceResponse.setDeviceName(saasDeviceInfo.getDeviceName());
        deviceResponse.setDeviceAlias(saasDeviceInfo.getDeviceAlias());
        deviceResponse.setCategoryId(saasDeviceInfo.getCategoryId());
        Map<String, String> deviceProfiles = rexolarApiClient.getDeviceProfiles(token);
        if (deviceProfiles != null && deviceProfiles.get(saasDeviceInfo.getCategoryId()) != null) {
            deviceResponse.setCategoryName(deviceProfiles.get(saasDeviceInfo.getCategoryId()) == null ? "" : deviceProfiles.get(saasDeviceInfo.getCategoryId()));
        }
//        if (deviceResponse.getCategoryName().contains("网关") || Constants.GW_ZIGBEE.equals(deviceResponse.getCategoryName())) {
//            deviceResponse.setNodeType("gateway");
//        } else {
//            deviceResponse.setNodeType("device");
//        }
        if ("default".equals(deviceResponse.getCategoryName())) {
            deviceResponse.setNodeType("device");
        } else {
            deviceResponse.setNodeType("gateway");
        }
        Map<String, Object> deviceAttributes = rexolarApiClient.getDeviceAttributes(saasDeviceInfo.getCoreId(), token,
                new String[]{Constants.LAST_ACTIVITY_TIME, Constants.ACTIVE, Constants.Version, Constants.ModelId, "power", Constants.DEV_STATUS, Constants.RSSI, "IPAddress", "zigbeeChannel"});
        if (deviceAttributes != null) {
            String modelId = deviceAttributes.get(Constants.ModelId) == null ? "UNDEFINED" : deviceAttributes.get(Constants.ModelId).toString();
            String ipAddress = deviceAttributes.get("IPAddress") == null ? "" : deviceAttributes.get("IPAddress").toString();
            String zigbeeChannel = deviceAttributes.get("zigbeeChannel") == null ? "" : deviceAttributes.get("zigbeeChannel").toString();
            String modelName = modelMap.get(modelId);
            if(StringUtils.isEmpty(modelName)){
                log.warn("modelName is null, modelId:{}", modelId);
                modelName = "UNDEFINED";
            }
            if("default".equals(deviceResponse.getCategoryName())){
                deviceResponse.setCategoryName(modelName);
            }
            deviceResponse.setStatus(getDeivceStatus(deviceAttributes, saasDeviceInfo.getCoreId(), deviceResponse.getNodeType(), token));
            deviceResponse.setModelId(modelId);
            deviceResponse.setIpAddress(ipAddress);
            deviceResponse.setZigbeeChannel(zigbeeChannel);
            deviceResponse.setModelName(modelMap.get(modelId));
        }

        Map<String, List<DeviceTimeSeries>> deviceTimeSeriesMap = rexolarApiClient
                .getDeviceTimeSeriesLatest(saasDeviceInfo.getCoreId(), token, new String[]{}, false);
        long ts = 0;
        for (String key : deviceTimeSeriesMap.keySet()) {
            Map<String, String> map = new HashMap<>();
            List<DeviceTimeSeries> values = deviceTimeSeriesMap.get(key);
            JSONObject jsonObject = JSONObject.parseObject(values.get(0).toJSONString());
            map.put("value", jsonObject.getString("value"));
            map.put("key", key);
            Long tmpTs = jsonObject.getLong("ts");
            if (tmpTs > ts) {
                ts = tmpTs;
            }
            if(Constants.RSSI.equals(key)){
                deviceResponse.setRssi(jsonObject.getString("value"));
            }
        }
        deviceResponse.setLastUpdateTime(ts);
        if(deviceResponse.getLastUpdateTime()==0){
            if(deviceAttributes.get(Constants.LAST_ACTIVITY_TIME)==null){
                log.warn("getDeviceResponse deviceTimeSeriesMap is null, deviceName:{}", saasDeviceInfo.getDeviceName());
            }else {
                deviceResponse.setLastUpdateTime((Long) deviceAttributes.get(Constants.LAST_ACTIVITY_TIME));
            }
        }
        return deviceResponse;
    }

    private Integer getDeivceStatus(Map<String, Object> deviceAttributes, String coreId, String nodeType, String token) {
        if(nodeType.equals("gateway")){
            boolean active = (boolean) deviceAttributes.get(Constants.ACTIVE);
            return active? 1 : 0;
        }else {
            if (deviceAttributes.get("devStatus") == null) {
                log.error("getDeviceStatus devStatus is null, deviceBasicData:{}", coreId);
                return 0;
            }else {
                int devStatus = Integer.parseInt(deviceAttributes.get("devStatus").toString());
                if(devStatus==1){
                    String gwCoreId = deviceGwRelationCache.getIfPresent(coreId);
                    if(gwCoreId==null) {
                        List<DeviceBasicData> gwRelations = rexolarApiClient.getFromRelationsInfo(token, coreId);
                        if (CollectionUtils.isEmpty(gwRelations)) {
                            log.error("getDeviceStatus rexolarApiClient.getFromRelationsInfo error, deviceBasicData:{}", coreId);
                            return 0;
                        } else {
                            gwCoreId = gwRelations.get(0).getCoreId();
                            deviceGwRelationCache.put(coreId, gwCoreId);
                        }
                    }
                    Integer gwStatus = gwStatusCache.getIfPresent(gwCoreId);
                    if(gwStatus==null){
                        Map<String, Object> gwAttributes = rexolarApiClient.getDeviceAttributes(gwCoreId, token,
                                new String[]{Constants.ACTIVE});
                        if(CollectionUtils.isEmpty(gwAttributes)){
                            log.error("getDeviceStatus gwAttributes active rexolarApiClient.getDeviceAttributes empty, deviceBasicData:{}", coreId);
                            return 0;
                        }else {
                            boolean active = (boolean) gwAttributes.get(Constants.ACTIVE);
                            if(!active){
                                log.warn("getDeviceStatus gwAttributes active is false, gwCoreId:{}", gwCoreId);
                                gwStatusCache.put(gwCoreId, 0);
                                return 0;
                            }else {
                                gwStatusCache.put(gwCoreId, 1);
                            }
                        }
                    }else {
                        if(gwStatus==0){
                            return 0;
                        }
                    }
                }
                return devStatus;
            }
        }
    }


    public List<AlarmResponse> alarms(String token) {
        List<AlarmResponse> responseList = new ArrayList<>();
        List<Map<String, String>> alarms = rexolarApiClient.getAlarms(token);
        if (!CollectionUtils.isEmpty(alarms)) {
            for (Map<String, String> alarm : alarms) {
                AlarmResponse alarmResponse = new AlarmResponse();
                alarmResponse.setAlarmName(alarm.get("name"));
                alarmResponse.setDeviceName(alarm.get("gwName"));
                alarmResponse.setDeviceAlias(alarm.get("gwAlias"));
                alarmResponse.setStartTime(alarm.get("startTime"));
                alarmResponse.setStatus(alarm.get("status"));
                alarmResponse.setId(alarm.get("id"));
                responseList.add(alarmResponse);
            }
        }
        return responseList;
    }

    public List<DeviceResponse> rssiInfo(DeviceListRequest deviceListRequest, String token) {
        return list(deviceListRequest.getSpaceId(),token);
    }

    public boolean delete(DeviceBasicData deviceBasicData, String token, String tenantId) {
        assetService.deleteDevice(tenantId, deviceBasicData.getName());
        Map<String, String> deviceProfiles = rexolarApiClient.getDeviceProfiles(token);
        if (CollectionUtils.isEmpty(deviceProfiles)) {
            log.error("delete deleteDevice deviceProfiles is empty, deviceName:{}", deviceBasicData.getName());
            return false;
        }
        String profileName = deviceProfiles.get(deviceBasicData.getProfileId());
        if (!StringUtils.isEmpty(profileName)
                && (profileName.contains("网关") || Constants.GW_ZIGBEE.equals(profileName))) {
            rexolarApiClient.getToRelationsInfo(token, deviceBasicData.getCoreId(), "DEVICE").forEach(subDevice -> {
                rexolarApiClient.deleteDevice(subDevice.getCoreId(), token);
            });
        } else {
            List<DeviceBasicData> gwList = rexolarApiClient.getFromRelationsInfo(token, deviceBasicData.getCoreId());
            if (!CollectionUtils.isEmpty(gwList)) {
                for (DeviceBasicData gw : gwList) {
                    HashMap dataMap = new HashMap();
                    dataMap.put(Constants.Version, "1.0");
                    dataMap.put("VendorCode", "Rexense");
                    String time = String.valueOf(System.currentTimeMillis());
                    dataMap.put("Timestamp", time);
                    dataMap.put("Seq", gw.getName() + "-" + time);
                    dataMap.put("DeviceId", gw.getName());
                    dataMap.put("FunctionCode", "DeleteDev");
                    HashMap payload = new HashMap();
                    JSONArray unbindSubDeviceList = new JSONArray();
                    unbindSubDeviceList.addAll(Collections.singleton(deviceBasicData.getName()));
                    payload.put("DeviceIds", unbindSubDeviceList);
                    dataMap.put("Payload", payload);
                    boolean gwFlag = rexolarApiClient.updateDeviceAttributes(gw.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
                    if (!gwFlag) {
                        log.error("delete unbind error, deviceName:{}", deviceBasicData.getName());
                        return false;
                    }
                }
            }
        }
        return rexolarApiClient.deleteDevice(deviceBasicData.getCoreId(), token);
    }

    public boolean addSubDevice(DeviceInfoData data) {
        SaasDeviceInfo deviceInfo = new SaasDeviceInfo();
        BeanUtils.copyProperties(data, deviceInfo);
        deviceInfo.setGmtCreated(new Date());
        deviceInfo.setGmtModified(new Date());
        return saasDeviceInfoMapper.insert(deviceInfo) == 1;
    }

    public List<SaasDeviceInfo> getByDeviceName(String deviceName) {
        LambdaQueryWrapper<SaasDeviceInfo> allQueryWrapper = new LambdaQueryWrapper<>();
        allQueryWrapper.eq(SaasDeviceInfo::getDeviceName, deviceName);
        return saasDeviceInfoMapper.selectList(allQueryWrapper);
    }

    public List<DeviceInfoData> customerList(DeviceListRequest deviceListRequest, String token) {
        List<DeviceInfoData> responseList = new ArrayList<>();
        LambdaQueryWrapper<SaasDeviceInfo> allQueryWrapper = new LambdaQueryWrapper<>();
        allQueryWrapper.eq(SaasDeviceInfo::getTenantId, JwtUtils.getTenantId(token));
        allQueryWrapper.eq(SaasDeviceInfo::getCustomerId, JwtUtils.getCustomerId(token));
        if (!StringUtils.isEmpty(deviceListRequest.getCategoryId())) {
            allQueryWrapper.eq(SaasDeviceInfo::getCategoryId, deviceListRequest.getCategoryId());
        }
        if (!StringUtils.isEmpty(deviceListRequest.getCategoryName())) {
            allQueryWrapper.eq(SaasDeviceInfo::getCategoryName, deviceListRequest.getCategoryName());
        }
        if (!StringUtils.isEmpty(deviceListRequest.getSpaceInfoId())) {
            LambdaQueryWrapper<SaasSpaceDeviceRelation> saasAssetDeviceRelationLambdaQueryWrapper = new LambdaQueryWrapper<>();
            saasAssetDeviceRelationLambdaQueryWrapper.eq(SaasSpaceDeviceRelation::getTenantId, JwtUtils.getTenantId(token));
            saasAssetDeviceRelationLambdaQueryWrapper.eq(SaasSpaceDeviceRelation::getSpaceInfoId, deviceListRequest.getSpaceInfoId());
            List<SaasSpaceDeviceRelation> list = saasSpaceDeviceRelationMapper.selectList(saasAssetDeviceRelationLambdaQueryWrapper);
            if (list.isEmpty()) {
                return responseList;
            }
            List<String> deviceNames = list.stream().map(SaasSpaceDeviceRelation::getDeviceName).collect(Collectors.toList());
            allQueryWrapper.in(SaasDeviceInfo::getDeviceName, deviceNames);
        }
        List<SaasDeviceInfo> deviceInfos = saasDeviceInfoMapper.selectList(allQueryWrapper);
        String tenantId = JwtUtils.getTenantId(token);
        String tenantToken = rexolarApiClient.getTenantToken(tenantId);
        Map<String, String> deviceProfiles = rexolarApiClient.getDeviceProfilesImage(tenantToken);
        for (SaasDeviceInfo deviceInfo : deviceInfos) {
            DeviceInfoData deviceInfoData = new DeviceInfoData();
            BeanUtils.copyProperties(deviceInfo, deviceInfoData);
            deviceInfoData.setCategoryImage(deviceProfiles.get(deviceInfoData.getCategoryId()));
            Map<String, Object> deviceAttributes = rexolarApiClient.getDeviceAttributes(deviceInfoData.getCoreId(), tenantToken,
                    new String[]{Constants.ACTIVE, Constants.WiFi0});
            if (deviceAttributes != null) {
                deviceInfoData.setLastUpdateTime(deviceAttributes.get(Constants.LAST_ACTIVITY_TIME) == null ? 0 : Long.parseLong(deviceAttributes.get(Constants.LAST_ACTIVITY_TIME).toString()));
                deviceInfoData.setStatus("true".equals(deviceAttributes.get(Constants.ACTIVE).toString()) ? 1 : 0);
                if (deviceAttributes.get(Constants.WiFi0) != null){
                    Map jsonObject = (Map) deviceAttributes.get(Constants.WiFi0);
                    if (jsonObject!= null) deviceInfoData.setWifiRssi(jsonObject.get(Constants.RSSI) == null ? null :Integer.parseInt(jsonObject.get(Constants.RSSI).toString()));
                }
            }
            Map<String, List<DeviceTimeSeries>> deviceTimeSeriesMap = rexolarApiClient.getDeviceTimeSeriesLatest(deviceInfoData.getCoreId(), tenantToken,
                    new String[]{Constants.ActivePower_1, Constants.PowerSwitch_1}, false);
            if (!CollectionUtils.isEmpty(deviceTimeSeriesMap)){
                List<DeviceTimeSeries> values = deviceTimeSeriesMap.get(Constants.ActivePower_1);
                JSONObject jsonObject = JSONObject.parseObject(values.get(0).toJSONString());
                if(jsonObject.get("value")==null){
//                    log.error("customerList values is null  error, deviceTimeSeriesMap：{}", deviceTimeSeriesMap);
                    deviceInfoData.setPower(0f);
                }else {
                    float power = Float.parseFloat(jsonObject.getString("value"));
                    deviceInfoData.setPower(power);
                }
                List<DeviceTimeSeries> powerSwitchValues = deviceTimeSeriesMap.get(Constants.PowerSwitch_1);
                JSONObject powerSwitchJsonObject = JSONObject.parseObject(powerSwitchValues.get(0).toJSONString());
                if(powerSwitchJsonObject.get(Constants.PowerSwitch_1)!=null){
                    deviceInfoData.setPowerSwitch_1(powerSwitchJsonObject.getBoolean(Constants.PowerSwitch_1));
                }
            }

            List<SaasDeviceLabelRelation> labels = saasDeviceLabelRelationMapper.selectList(new LambdaQueryWrapper<SaasDeviceLabelRelation>().eq(SaasDeviceLabelRelation::getDeviceName, deviceInfoData.getDeviceName()));
            if (!CollectionUtils.isEmpty(labels)) {
                if (labels.size() > 1) {
                    log.warn("getDeviceByName error, labels size > 1, size:{}", labels.size());
                }
                SaasDeviceLabelRelation label = labels.get(0);
                if (label.getSpaceLabelId() != null) {
                    deviceInfoData.setSpaceLabelId(label.getSpaceLabelId());
                    SaasSpaceLabel saasSpaceLabel = saasSpaceLabelMapper.selectById(label.getSpaceLabelId());
                    if (saasSpaceLabel != null) {
                        deviceInfoData.setSpaceLabel(saasSpaceLabel.getLabelName());
                        deviceInfoData.setSpaceLabelIconUrl(saasSpaceLabel.getIconUrl());
                    }
                }
                if (label.getLabelId() != null) {
                    deviceInfoData.setDeviceLabelId(label.getLabelId());
                    SaasDeviceLabel saasDeviceLabel = saasDeviceLabelMapper.selectById(label.getLabelId());
                    if (saasDeviceLabel != null) {
                        deviceInfoData.setDeviceLabel(saasDeviceLabel.getLabelName());
                        deviceInfoData.setDeviceLabelIconUrl(saasDeviceLabel.getIconUrl());
                    }
                }
            }

            List<SaasSpaceDeviceRelation> spaceDeviceRelations = saasSpaceDeviceRelationMapper.selectList(new LambdaQueryWrapper<SaasSpaceDeviceRelation>().eq(SaasSpaceDeviceRelation::getDeviceName, deviceInfoData.getDeviceName()));
            if (!CollectionUtils.isEmpty(spaceDeviceRelations)){
                deviceInfoData.setSpaceInfoId(spaceDeviceRelations.get(0).getSpaceInfoId());
            }
            responseList.add(deviceInfoData);
        }
        return responseList;
    }

    public SaasDeviceInfo getDeviceByName(String deviceName, String tenantId) {
        LambdaQueryWrapper<SaasDeviceInfo> allQueryWrapper = new LambdaQueryWrapper<>();
        allQueryWrapper.eq(SaasDeviceInfo::getTenantId, tenantId);
        allQueryWrapper.eq(SaasDeviceInfo::getDeviceName, deviceName);
        List<SaasDeviceInfo> list = saasDeviceInfoMapper.selectList(allQueryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            log.error("getDeviceByName is empty error, deviceName:{}", deviceName);
            return null;
        }
        return list.get(0);
    }

    public List<SaasDeviceInfo> getDeviceByUser(String customerId) {
        LambdaQueryWrapper<SaasDeviceInfo> allQueryWrapper = new LambdaQueryWrapper<>();
        allQueryWrapper.eq(SaasDeviceInfo::getCustomerId, customerId);
        return saasDeviceInfoMapper.selectList(allQueryWrapper);
    }

    public boolean deleteCustomerDevice(SaasDeviceInfo device, String token) {
        String customerId = JwtUtils.getCustomerId(token);
        long now = System.currentTimeMillis();
        Map<String,  Object> leaveDevice = new HashMap<>();
        leaveDevice.put(Constants.Version, "1.0");
        leaveDevice.put("VendorCode", "Rexense");
        leaveDevice.put("Timestamp", now);
        leaveDevice.put("Seq", device.getDeviceName() + "-" + now);
        leaveDevice.put("DeviceId", device.getDeviceName());
        leaveDevice.put("FunctionCode", "InvokeCmd");
        Map<String, Object> payload = new HashMap<>();
        payload.put("NetworkLeave", "");
        leaveDevice.put("Payload", payload);
        boolean leaveDeviceResult = rexolarApiClient.updateDeviceAttributes(device.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(leaveDevice), token);
        if (!leaveDeviceResult){
            log.error("deleteCustomerDevice leaveDevice error, deviceName:{}", device.getDeviceName());
        }

        boolean result = rexolarApiClient.deleteCustomerDevice(device.getCoreId(), customerId, token);
        if (!result) {
            log.error("deleteCustomerDevice error, deviceName:{}", device.getDeviceName());
            return false;
        }
        saasSpaceDeviceRelationMapper.delete(new LambdaQueryWrapper<SaasSpaceDeviceRelation>()
                .eq(SaasSpaceDeviceRelation::getDeviceName, device.getDeviceName()));
        device.setCustomerId("");
        device.setDeviceAlias("");
        device.setGmtModified(new Date());
        device.setGmtBind(null);
        saasDeviceLabelRelationMapper.delete(new LambdaQueryWrapper<SaasDeviceLabelRelation>()
                .eq(SaasDeviceLabelRelation::getDeviceName, device.getDeviceName()));
        return saasDeviceInfoMapper.updateById(device) == 1;
    }

    public boolean batchAdd(List<BatchAddCtRequest> batchAddCtRequests, String categroyId, String categroyName, String token) {
        for (BatchAddCtRequest batchAddCtRequest : batchAddCtRequests) {
            LambdaQueryWrapper<SaasDeviceInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SaasDeviceInfo::getDeviceName, batchAddCtRequest.getDeviceName());
            List<SaasDeviceInfo> devices = saasDeviceInfoMapper.selectList(queryWrapper);
            if (!CollectionUtils.isEmpty(devices)) {
                log.error("batchAddCtRequest deviceName is exist, deviceName:{}", batchAddCtRequest.getDeviceName());
                return false;
            }
            SaasDeviceInfo saasDeviceInfo = new SaasDeviceInfo();
            saasDeviceInfo.setGmtCreated(new Date());
            saasDeviceInfo.setGmtModified(new Date());
            saasDeviceInfo.setType(DeviceTypeEnum.DEVICE.getCode());
            saasDeviceInfo.setCategoryId(categroyId);
            saasDeviceInfo.setCategoryName(categroyName);
            saasDeviceInfo.setDeviceName(batchAddCtRequest.getDeviceName());
            saasDeviceInfo.setTenantId(JwtUtils.getTenantId(token));
            DeviceBasicData deviceBasicData = rexolarApiClient.getDeviceByDeviceName(batchAddCtRequest.getDeviceName(), token);
            if (deviceBasicData != null) {
                log.warn("batchAddCtRequest gwName is exist, gwName:{}", batchAddCtRequest.getDeviceName());
                String deviceId = deviceBasicData.getCoreId();
                saasDeviceInfo.setCoreId(deviceId);
            } else {
                String deviceId = generateDevice(batchAddCtRequest, categroyId, false, token);
                if (StringUtils.isEmpty(deviceId)) {
                    log.error("batchAddCtRequest error, gwName:{}", batchAddCtRequest.getDeviceName());
                    return false;
                }
                saasDeviceInfo.setCoreId(deviceId);
            }
            if (saasDeviceInfoMapper.insert(saasDeviceInfo) != 1) {
                log.error("batchAddCtRequest insert saasDeviceInfo error, saasDeviceInfo:{}", saasDeviceInfo);
                return false;
            }
        }
        return true;
    }

    private String generateDevice(BatchAddCtRequest batchAddCtRequest, String profileId, boolean isGw, String token) {
        DynamicCreateDevice device = new DynamicCreateDevice();
        DynamicCreateDevice.DeviceBean deviceBean = new DynamicCreateDevice.DeviceBean();
        DynamicCreateDevice.DeviceProfileId deviceProfileId = new DynamicCreateDevice.DeviceProfileId();
        DynamicCreateDevice.Credentials mqttBasicCredentials = new DynamicCreateDevice.Credentials();
        DynamicCreateDevice.AdditionalInfo additionalInfo = new DynamicCreateDevice.AdditionalInfo();

        deviceBean.setName(batchAddCtRequest.getDeviceName());
        deviceBean.setLabel(batchAddCtRequest.getDeviceName());
        deviceProfileId.setId(profileId);
        deviceBean.setDeviceProfileId(deviceProfileId);
        additionalInfo.setGateway(isGw);
        additionalInfo.setOverwriteActivityTime(true);
        deviceBean.setAdditionalInfo(additionalInfo);

        DynamicCreateDevice.CredentialsValue credentialsValue = new DynamicCreateDevice.CredentialsValue();
        credentialsValue.setClientId(batchAddCtRequest.getClientId());
        credentialsValue.setUserName(batchAddCtRequest.getUsername());
        credentialsValue.setPassword(batchAddCtRequest.getPassword());


        mqttBasicCredentials.setCredentialsValue(JSON.toJSONString(credentialsValue));

        device.setDevice(deviceBean);
        device.setCredentials(mqttBasicCredentials);

        String data = JSON.toJSONString(device);
        String coreId = rexolarApiClient.dynamicCreateDevice(data, token);
        if (StringUtils.isEmpty(coreId)) {
            log.error("generateDevice dynamicCreateDevice error, data:{}", data);
            return null;
        }
        return coreId;
    }

    public boolean ctSet(CtSetRequest ctSetRequest, String token) {
        String tenantId = JwtUtils.getTenantId(token);
        String tenantToken = rexolarApiClient.getTenantToken(tenantId);
        if (StringUtils.isEmpty(tenantToken)) {
            log.error("ctSet tenantToken is null, tenantId:{}", tenantId);
            return false;
        }
        DeviceBasicData deviceBasicData = rexolarApiClient.getDeviceByDeviceName(ctSetRequest.getDeviceName(), tenantToken);
        if (deviceBasicData == null) {
            log.error("ctSet getDeviceByDeviceName error, gwName:{}", ctSetRequest.getDeviceName());
            return false;
        }
        HashMap dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", ctSetRequest.getDeviceName() + "-" + time);
        dataMap.put("DeviceId", ctSetRequest.getDeviceName());
        dataMap.put("FunctionCode", "SetStatus");
        HashMap payload = new HashMap();
        String values = ctSetRequest.getL3() + ctSetRequest.getL2() + ctSetRequest.getL1() + "0";
        int decimalValue = Integer.parseInt(values, 2);
        payload.put("Current_Direction_1", decimalValue);
        dataMap.put("Payload", payload);
        boolean result = rexolarApiClient.updateDeviceAttributes(deviceBasicData.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), tenantToken);
        if (!result) {
            log.error("ctSet updateDeviceAttributes error, gwName:{}", ctSetRequest.getDeviceName());
            return false;
        }
        SaasDeviceEvent event = new SaasDeviceEvent();
        event.setDeviceName(ctSetRequest.getDeviceName());
        event.setType(Constants.ALARM_CODE_CT_DIRECT);
        event.setContent(JSON.toJSONString(ctSetRequest));
        event.setGmtCreated(new Date());
        return saasDeviceEventMapper.insert(event) == 1;
    }

    public List<SaasDeviceEvent> events(EventsRequest eventsRequest, String token) {
        LambdaQueryWrapper<SaasDeviceEvent> queryWrapper = new LambdaQueryWrapper<SaasDeviceEvent>()
                .eq(SaasDeviceEvent::getDeviceName, eventsRequest.getDeviceName());
        if (eventsRequest.getType() != null) {
            queryWrapper.eq(SaasDeviceEvent::getType, eventsRequest.getType());
        }
        queryWrapper.between(SaasDeviceEvent::getGmtCreated, new Date(eventsRequest.getStartTime()), new Date(eventsRequest.getEndTime()));
        return saasDeviceEventMapper.selectList(queryWrapper);
    }

    public PaasGatewayDeviceRelation getGwByDevcieName(String deviceName) {
        LambdaQueryWrapper<PaasGatewayDeviceRelation> queryWrapper = new LambdaQueryWrapper<PaasGatewayDeviceRelation>()
                .eq(PaasGatewayDeviceRelation::getDeviceName, deviceName);
        return paasGatewayDeviceRelationMapper.selectOne(queryWrapper);
    }

    public boolean bindCustomerDevice(SaasDeviceInfo deviceInfo, String customerId, String token) {
        boolean result = rexolarApiClient.addCustomerDevice(deviceInfo.getCoreId(), customerId, token);
        if (!result) {
            log.error("bind addCustomerDevice error, gwName:{}", deviceInfo.getDeviceName());
            return false;
        }
        deviceInfo.setCustomerId(customerId);
        deviceInfo.setGmtModified(new Date());
        deviceInfo.setGmtBind(new Date());
        if (saasDeviceInfoMapper.updateById(deviceInfo) != 1) {
            log.error("bind update saasDeviceInfo error, gwName:{}", deviceInfo.getDeviceName());
            return false;
        }
        return true;
    }

    public List<SaasDeviceInfo> alllist() {
        LambdaQueryWrapper<SaasDeviceInfo> allQueryWrapper = new LambdaQueryWrapper<>();
        return saasDeviceInfoMapper.selectList(allQueryWrapper);
    }

    public List<SaasDeviceInfo> getAllCtList() {
        LambdaQueryWrapper<SaasDeviceInfo> allQueryWrapper = new LambdaQueryWrapper<>();
        allQueryWrapper.eq(SaasDeviceInfo::getCategoryName, Constants.CT_PROFILE_NAME);
        return saasDeviceInfoMapper.selectList(allQueryWrapper);
    }

    public boolean uploadLog(EdgeLogRequest edgeLogRequest, String token) {
        SaasDeviceLog saasDeviceLog = new SaasDeviceLog();
        saasDeviceLog.setDeviceName(edgeLogRequest.getDeviceName());
        saasDeviceLog.setLogUrl(edgeLogRequest.getLogUrl());
        saasDeviceLog.setGmtCreated(new Date());
        saasDeviceLog.setTenantId(JwtUtils.getTenantId(token));
        saasDeviceLog.setCustomerId(JwtUtils.getCustomerId(token));

        SaasUserInfo saasUserInfo = saasUserInfoMapper.selectById(JwtUtils.getUserId(token));
        if (saasUserInfo == null) {
            log.error("uploadLog saasUserInfo is null, userId:{}", JwtUtils.getUserId(token));
        } else {
            saasDeviceLog.setUserEmail(saasUserInfo.getMail());
        }
        if (saasDeviceLogMapper.insert(saasDeviceLog) != 1) {
            log.error("uploadLog insert saasDeviceLog error, saasDeviceLog:{}", saasDeviceLog);
            return false;
        }
        return true;
    }

    public String getEdgeLog(String deviceName, String token) {
        LambdaQueryWrapper<SaasDeviceLog> queryWrapper = new LambdaQueryWrapper<SaasDeviceLog>()
                .eq(SaasDeviceLog::getDeviceName, deviceName)
                .orderByDesc(SaasDeviceLog::getGmtCreated)
                .last("limit 1");
        SaasDeviceLog saasDeviceLog = saasDeviceLogMapper.selectOne(queryWrapper);
        if (saasDeviceLog == null) {
            log.warn("getEdgeLog saasDeviceLog is null, gwName:{}", deviceName);
            return null;
        }
        return saasDeviceLog.getLogUrl();
    }

    public boolean updateAlias(Long deviceId, String alias) {
        SaasDeviceInfo deviceInfo = saasDeviceInfoMapper.selectById(deviceId);
        deviceInfo.setDeviceAlias(alias);
        deviceInfo.setGmtModified(new Date());
        return saasDeviceInfoMapper.updateById(deviceInfo) == 1;
    }

    public CtDevicePowerResponse ctPower(DeviceBasicData deviceBasicData, String tenantToken) {
        CtDevicePowerResponse response = new CtDevicePowerResponse();
        String deviceId = deviceBasicData.getCoreId();
        response.setCoreId(deviceBasicData.getCoreId());
        response.setDeviceName(deviceBasicData.getName());
        response.setDeviceAlias(deviceBasicData.getLabel());
        Map<String, List<DeviceTimeSeries>> deviceTimeSeriesMap = rexolarApiClient.getDeviceTimeSeriesLatest(
                deviceId, tenantToken, new String[]{Constants.TotalActivePower_1, Constants.TotalCEI_1, Constants.TotalCEE_1}, false);
        for (String key : deviceTimeSeriesMap.keySet()) {
            List<DeviceTimeSeries> values = deviceTimeSeriesMap.get(key);
            JSONObject jsonObject = JSONObject.parseObject(values.get(0).toJSONString());
            if (Constants.TotalActivePower_1.equals(key)) {
                response.setPower(jsonObject.getString("value"));
            } else if (Constants.TotalCEI_1.equals(key)) {
                response.setImportEnergy(jsonObject.getString("value"));
            } else if (Constants.TotalCEE_1.equals(key)) {
                response.setExportEnergy(jsonObject.getString("value"));
            }
        }
        return response;
    }

    public Boolean saveDeviceEvent(DeviceEventData deviceEventData) {
        SaasDeviceEvent saasDeviceEvent = new SaasDeviceEvent();
        saasDeviceEvent.setDeviceName(deviceEventData.getDeviceName());
        saasDeviceEvent.setType(deviceEventData.getCode());
        saasDeviceEvent.setGmtCreated(new Date(deviceEventData.getTime()));
        if (saasDeviceEventMapper.insert(saasDeviceEvent) != 1) {
            log.error("saveDeviceEvent insert saasDeviceEvent error, saasDeviceEvent:{}", saasDeviceEvent);
            return false;
        }
        return true;
    }

    public SaasSpaceDeviceRelation getSpaceIdByDeviceName(String deviceName) {
        List<SaasSpaceDeviceRelation> list = saasSpaceDeviceRelationMapper.selectList(new LambdaQueryWrapper<SaasSpaceDeviceRelation>()
                .eq(SaasSpaceDeviceRelation::getDeviceName, deviceName));
        if (CollectionUtils.isEmpty(list)) {
            log.error("getSpaceIdByDeviceName saasSpaceDeviceRelation is null, gwName:{}", deviceName);
            return null;
        }
        if (list.size() > 1) {
            log.error("getSpaceIdByDeviceName saasSpaceDeviceRelation size > 1, gwName:{}", deviceName);
        }
        return list.get(0);
    }

    @Transactional
    public boolean setLabel(DeviceLabelRequest deviceLabelRequest, String labelName) {
        List<SaasDeviceInfo> devices = saasDeviceInfoMapper.selectList(new LambdaQueryWrapper<SaasDeviceInfo>()
                .eq(SaasDeviceInfo::getDeviceName, deviceLabelRequest.getDeviceName()));
        if (CollectionUtils.isEmpty(devices)) {
            log.error("setLabel saasDeviceInfo is null, gwName:{}", deviceLabelRequest.getDeviceName());
            return false;
        }
        if (devices.size() > 1) {
            log.error("setLabel saasDeviceInfo size > 1, gwName:{}", deviceLabelRequest.getDeviceName());
        }
        SaasDeviceInfo deviceInfo = devices.get(0);
        List<SaasDeviceLabelRelation> relations = saasDeviceLabelRelationMapper.selectList(
                new LambdaQueryWrapper<SaasDeviceLabelRelation>().eq(SaasDeviceLabelRelation::getDeviceName, deviceInfo.getDeviceName()));
        if (CollectionUtils.isEmpty(relations)) {
            SaasDeviceLabelRelation saasDeviceLabelRelation = new SaasDeviceLabelRelation();
            saasDeviceLabelRelation.setDeviceName(deviceInfo.getDeviceName());
            saasDeviceLabelRelation.setLabelId(deviceLabelRequest.getDeviceLabelId());
            saasDeviceLabelRelation.setSpaceLabelId(deviceLabelRequest.getSpaceLabelId());
            saasDeviceLabelRelation.setTenantId(deviceInfo.getTenantId());
            saasDeviceLabelRelation.setCustomerId(deviceInfo.getCustomerId());
            if (saasDeviceLabelRelationMapper.insert(saasDeviceLabelRelation) != 1) {
                log.error("setLabel insert saasDeviceLabelRelation error, saasDeviceLabelRelation:{}", saasDeviceLabelRelation);
                return false;
            }
        } else if (relations.size() > 1) {
            log.error("setLabel saasDeviceLabelRelation size > 1, gwName:{}", deviceLabelRequest.getDeviceName());
        } else {
            SaasDeviceLabelRelation saasDeviceLabelRelation = relations.get(0);
            saasDeviceLabelRelation.setLabelId(deviceLabelRequest.getDeviceLabelId());
            saasDeviceLabelRelation.setSpaceLabelId(deviceLabelRequest.getSpaceLabelId());
            saasDeviceLabelRelation.setGmtModified(new Date());
            if (saasDeviceLabelRelationMapper.updateById(saasDeviceLabelRelation) != 1) {
                log.error("setLabel update saasDeviceLabelRelation error, saasDeviceLabelRelation:{}", saasDeviceLabelRelation);
                return false;
            }
        }
        if (!StringUtils.isEmpty(labelName)) {
            deviceInfo.setDeviceAlias(labelName);
            deviceInfo.setGmtModified(new Date());
            if (saasDeviceInfoMapper.updateById(deviceInfo) != 1) {
                log.error("setLabel update saasDeviceInfo error, saasDeviceInfo:{}", deviceInfo);
                throw new RuntimeException("setLabel update saasDeviceInfo error");
            }
        }
        return true;
    }

    public DeviceLabelResponse getDeviceLabels(String deviceName) {
        DeviceLabelResponse deviceLabelResponse = new DeviceLabelResponse();
        deviceLabelResponse.setDeviceName(deviceName);
        List<SaasDeviceLabelRelation> deviceLabels = saasDeviceLabelRelationMapper.selectList(new LambdaQueryWrapper<SaasDeviceLabelRelation>().eq(SaasDeviceLabelRelation::getDeviceName, deviceName));
        if (!CollectionUtils.isEmpty(deviceLabels)) {
            SaasDeviceLabelRelation saasDeviceLabelRelation = deviceLabels.get(0);
            if (saasDeviceLabelRelation.getSpaceLabelId() != null) {
                deviceLabelResponse.setSpaceLabelId(saasDeviceLabelRelation.getSpaceLabelId());
                SaasSpaceLabel saasSpaceLabel = saasSpaceLabelMapper.selectById(saasDeviceLabelRelation.getSpaceLabelId());
                if (saasSpaceLabel != null) {
                    deviceLabelResponse.setSpaceLabelName(saasSpaceLabel.getLabelName());
                    deviceLabelResponse.setSpaceIconUrl(saasSpaceLabel.getIconUrl());
                }
            }
            if (saasDeviceLabelRelation.getLabelId() != null) {
                deviceLabelResponse.setDeviceLabelId(saasDeviceLabelRelation.getLabelId());
                SaasDeviceLabel saasDeviceLabel = saasDeviceLabelMapper.selectById(saasDeviceLabelRelation.getLabelId());
                if (saasDeviceLabel != null) {
                    deviceLabelResponse.setDeviceLabelName(saasDeviceLabel.getLabelName());
                    deviceLabelResponse.setDeviceIconUrl(saasDeviceLabel.getIconUrl());
                }
            }
        }
        return deviceLabelResponse;
    }

    public boolean networkLeave(SaasDeviceInfo deviceInfo, String tenantToken) {
        JSONObject data = new JSONObject();
        data.put("functionCode", "InvokeCmd");
        data.put(Constants.Version, "1.0");
        data.put("VendorCode", "Rexense");
        long timestamp = System.currentTimeMillis();
        data.put("Timestamp", timestamp);
        data.put("DeviceId", deviceInfo.getDeviceName());
        data.put("Seq", deviceInfo.getDeviceName() + "-" + timestamp);
        JSONObject payload = new JSONObject();
        data.put("Payload", payload);
        return rexolarApiClient.updateDeviceAttributes(deviceInfo.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(data), tenantToken);
    }

    public boolean deleteCt(String deviceName, String token) {
        DeviceBasicData device = rexolarApiClient.getDeviceByDeviceName(deviceName, token);
        if (device != null) {
            boolean flag = rexolarApiClient.deleteDevice(device.getCoreId(), token);
            if (!flag) {
                log.error("deleteCt deleteDevice error, gwName:{}", deviceName);
                return false;
            }
        }
        LambdaQueryWrapper<SaasSpaceDeviceRelation> queryWrapper = new LambdaQueryWrapper<SaasSpaceDeviceRelation>()
                .eq(SaasSpaceDeviceRelation::getDeviceName, deviceName);
        queryWrapper.eq(SaasSpaceDeviceRelation::getTenantId, JwtUtils.getTenantId(token));
        saasSpaceDeviceRelationMapper.delete(queryWrapper);

        LambdaQueryWrapper<SaasDeviceLabelRelation> queryWrapper1 = new LambdaQueryWrapper<SaasDeviceLabelRelation>()
                .eq(SaasDeviceLabelRelation::getDeviceName, deviceName);
        queryWrapper1.eq(SaasDeviceLabelRelation::getTenantId, JwtUtils.getTenantId(token));
        saasDeviceLabelRelationMapper.delete(queryWrapper1);

        saasDeviceLabelRelationMapper.delete(new LambdaQueryWrapper<SaasDeviceLabelRelation>().eq(SaasDeviceLabelRelation::getDeviceName, deviceName));

        LambdaQueryWrapper<SaasDeviceInfo> queryWrapper2 = new LambdaQueryWrapper<SaasDeviceInfo>()
                .eq(SaasDeviceInfo::getDeviceName, deviceName);
        return saasDeviceInfoMapper.delete(queryWrapper2) == 1;
    }

    public boolean writeCtDevProperty(DeviceBasicData deviceBasicData, String token, WriteDevPropertyRequest writeDevPropertyRequest) {
        HashMap dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", deviceBasicData.getName() + "-" + time);
        dataMap.put("deviceId", deviceBasicData.getName());
        dataMap.put("FunctionCode", "SetStatus");
        HashMap payloadMap = new HashMap();
        payloadMap.put(writeDevPropertyRequest.getProperty(), writeDevPropertyRequest.getValue());
        dataMap.put("Payload", payloadMap);
        return rexolarApiClient.updateDeviceAttributes(deviceBasicData.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
    }

    public boolean invokeCtDevice(DeviceBasicData deviceBasicData, String token, InvokeCmdRequest invokeCmdRequest) {
        HashMap<String,  Object> dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", deviceBasicData.getName() + "-" + time);
        dataMap.put("deviceId", deviceBasicData.getName());
        dataMap.put("FunctionCode", "InvokeCmd");
        dataMap.put("Payload", invokeCmdRequest.getPayload());
        return rexolarApiClient.updateDeviceAttributes(deviceBasicData.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
    }

    public boolean syncGw(String token) {
        List<DeviceBasicData> devices = rexolarApiClient.getDeviceList(token);
        if(CollectionUtils.isEmpty( devices)){
            log.warn("syncGw getDeviceList is empty");
            return true;
        }
        Map<String, String> deviceProfiles = rexolarApiClient.getDeviceProfiles( token);
        if(CollectionUtils.isEmpty( deviceProfiles)){
            log.warn("syncGw getDeviceProfiles is empty");
            return true;
        }
        Map<String, String> deviceProfileMap = new HashMap<>();
        for (String key : deviceProfiles.keySet()){
            if (deviceProfiles.get(key).equals("网关配置") || deviceProfiles.get(key).equals("Zigbee网关")){
                deviceProfileMap.put(key, deviceProfiles.get(key));
            }
        }
        for (DeviceBasicData device : devices) {
            if (deviceProfileMap.containsKey(device.getProfileId())) {
                List<PaasGatewayCredentials> gws = paasGatewayCredentialsMapper.selectList(new LambdaQueryWrapper<PaasGatewayCredentials>()
                        .eq(PaasGatewayCredentials::getGwId, device.getCoreId()));
                if (CollectionUtils.isEmpty(gws)) {
                    PaasGatewayCredentials gw = new PaasGatewayCredentials();
                    gw.setGwId(device.getCoreId());
                    gw.setGwName(device.getName());
                    gw.setGwAlias(device.getName());
                    gw.setTenantId(JwtUtils.getTenantId(token));
                    gw.setProfileId(device.getProfileId());
                    Map<String, Object> credentials = rexolarApiClient.getDeviceCredentialsById(device.getCoreId(), token);
                    if(CollectionUtils.isEmpty( credentials)){
                        log.error("syncGw getDeviceCredentialsById is empty, device:{}", device);
                        continue;
                    }
                    //credentialsValue -> {"clientId":"C49894C293FA","userName":"C49894C293FA","password":"C49894C293FA"}
                    String credentialsStr = (String) credentials.get("credentialsValue");
                    if (StringUtils.isEmpty(credentialsStr)){
                        log.error("syncGw getDeviceCredentialsById credentialsValue is empty, device:{}", device);
                    }
                    JSONObject credentialsValue = JSON.parseObject(credentialsStr);

                    gw.setClientId(credentialsValue.getString("clientId"));
                    gw.setUsername(credentialsValue.getString("userName"));
                    gw.setPassword(credentialsValue.getString("password"));
                    gw.setStatus(GwStatusEnum.ON.getCode());
                    gw.setGmtCreate(new Date());
                    gw.setGmtModified(new Date());
                    if(paasGatewayCredentialsMapper.insert(gw)!=1){
                        log.error("syncGw gatewayCredentialsService save error, data:{}", device);
                    }
                }
            }
        }
        return true;
    }

    public boolean bindSpace(String deviceName, Long spaceId, Integer type, String token) {
        SaasSpaceInfo spaceInfo = saasSpaceInfoMapper.selectById(spaceId);
        if (spaceInfo == null){
            log.error("bindSpace space is not exist, spaceId:{}", spaceId);
            return false;
        }
        saasSpaceDeviceRelationMapper.delete(new LambdaQueryWrapper<SaasSpaceDeviceRelation>().eq(SaasSpaceDeviceRelation::getDeviceName, deviceName));
        SaasSpaceDeviceRelation relation = new SaasSpaceDeviceRelation();
        relation.setDeviceName(deviceName);
        relation.setSpaceInfoId(spaceId);
        relation.setSpaceId(spaceInfo.getCoreId());
        relation.setTenantId(JwtUtils.getTenantId( token));
        relation.setCustomerId(JwtUtils.getCustomerId( token));
        relation.setType(type);
        relation.setGmtCreated(new Date());
        relation.setGmtModified(new Date());
        return saasSpaceDeviceRelationMapper.insert(relation)==1;
    }

    public Map<String, Object> getAttributes(String gwName, String token, String[] strings) {
       return rexolarApiClient.getDeviceAttributes(gwName, token, strings);
    }

    public DeviceDetailResponseV2 detailV2(SaasDeviceInfo device, String token) {
        DeviceDetailResponseV2 response = new DeviceDetailResponseV2();
        BeanUtils.copyProperties(device, response);

        List<SaasSpaceDeviceRelation> relations = saasSpaceDeviceRelationMapper.selectList(new LambdaQueryWrapper<SaasSpaceDeviceRelation>()
                .eq(SaasSpaceDeviceRelation::getDeviceName, device.getDeviceName()));
        if (!CollectionUtils.isEmpty(relations)){
            SaasSpaceDeviceRelation relation = relations.get(0);
            SaasSpaceInfo spaceInfo = saasSpaceInfoMapper.selectById(relation.getSpaceInfoId());
            if (spaceInfo != null){
                response.setSpaceName(spaceInfo.getName());
            }
            response.setPosition(relation.getPosition());
        }
        Map<String, Object> attributes = rexolarApiClient.getDeviceAttributes(device.getCoreId(), token, new String[]{Constants.DEV_STATUS,
                Constants.ACTIVE, Constants.LAST_CONNECT_TIME, Constants.LAST_DISCONNECT_TIME, Constants.WiFi0});
        if (!CollectionUtils.isEmpty(attributes)){
            response.setLastConnectTime((attributes.get(Constants.LAST_CONNECT_TIME)==null? 0L : (Long) attributes.get(Constants.LAST_CONNECT_TIME)));
            response.setLastDisconnectTime((attributes.get(Constants.LAST_CONNECT_TIME)==null? 0L : (Long) attributes.get(Constants.LAST_CONNECT_TIME)));
            if(device.getType().equals(DeviceTypeEnum.SUB_DEVICE.getCode())){
                response.setStatus(attributes.get(Constants.DEV_STATUS)==null? 0 : (Integer) attributes.get(Constants.DEV_STATUS));
            }else {
                response.setStatus(attributes.get(Constants.ACTIVE)==null? 0 : (Integer) attributes.get(Constants.ACTIVE));
            }
            if (attributes.get(Constants.WiFi0) != null){
                Map jsonObject = (Map) attributes.get(Constants.WiFi0);
                if (jsonObject!= null) response.setWifiRssi(jsonObject.get(Constants.RSSI) == null ? null :Integer.parseInt(jsonObject.get(Constants.RSSI).toString()));
            }
        }
        Map<String, List<DeviceTimeSeries>> timeSeries = rexolarApiClient.getDeviceTimeSeriesLatest(device.getCoreId(), token, new String[]{}, false);
        List<TimeSeriesData> timeSeriesDataList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(timeSeries)){
            String productKey = device.getProductKey();
            if (productKey == null){
                log.warn("getDeviceByProductKey productKey is empty, device:{}", device);
                for (String key : timeSeries.keySet()){
                    TimeSeriesData timeSeriesData = new TimeSeriesData();
                    timeSeriesData.setKey(key);
                    timeSeriesData.setValue((String) timeSeries.get(key).get(0).get("value"));
                    timeSeriesData.setTs((Long) timeSeries.get(key).get(0).get("ts"));
                    timeSeriesDataList.add(timeSeriesData);
                }
            }else {
                TslModelResponse tslModelResponse = tslModelService.detail(productKey, JwtUtils.getTenantId(token));
                tslModelResponse.getProperties().forEach(property -> {
                    TslPropertyResponse tslProperty = JSONObject.parseObject(JSON.toJSONString(property), TslPropertyResponse.class);
                    if (timeSeries.containsKey(tslProperty.getIdentifier())){
                        TimeSeriesData timeSeriesData = new TimeSeriesData();
                        timeSeriesData.setKey(tslProperty.getIdentifier());
                        timeSeriesData.setValue((String) timeSeries.get(tslProperty.getIdentifier()).get(0).get("value"));
                        timeSeriesData.setTs((Long) timeSeries.get(tslProperty.getIdentifier()).get(0).get("ts"));
                        timeSeriesDataList.add(timeSeriesData);
                    }
                });
            }
        }
        response.setLatestTimeSeriesData(timeSeriesDataList);

        return null;
    }

    public List<DeviceInfoData> getDeviceByProductKey(String productKey, String token) {
        List<DeviceInfoData> result = new ArrayList<>();
        List<SaasDeviceInfo> list = saasDeviceInfoMapper.selectList(new LambdaQueryWrapper<SaasDeviceInfo>()
                .eq(SaasDeviceInfo::getProductKey, productKey)
                .eq(SaasDeviceInfo::getTenantId, JwtUtils.getTenantId(token)));
        if (CollectionUtils.isEmpty(list)){
            return result;
        }
        List<String> deviceNames = list.stream().map(SaasDeviceInfo::getDeviceName).collect(Collectors.toList());
        List<SaasSpaceDeviceRelation> relations = saasSpaceDeviceRelationMapper.selectList(new LambdaQueryWrapper<SaasSpaceDeviceRelation>()
                .in(SaasSpaceDeviceRelation::getDeviceName, deviceNames));
        Map<Long, SaasSpaceInfo> spaceMap = new HashMap<>();
        Map<String, SaasSpaceDeviceRelation> relationMap = new HashMap<>();
        if(!CollectionUtils.isEmpty( relations)){
            relationMap = relations.stream().collect(Collectors.toMap(SaasSpaceDeviceRelation::getDeviceName, relation -> relation));
            List<Long> spaceIds = relations.stream().map(SaasSpaceDeviceRelation::getSpaceInfoId).collect(Collectors.toList());
//            List<SaasSpaceInfo> spaces = saasSpaceInfoMapper.selectList(new LambdaQueryWrapper<SaasSpaceInfo>().in(SaasSpaceInfo::getId, spaceIds));
//            spaceMap = spaces.stream().collect(Collectors.toMap(SaasSpaceInfo::getId, space -> space));
        }
        for (SaasDeviceInfo device : list){
            DeviceInfoData deviceInfoData = new DeviceInfoData();
            BeanUtils.copyProperties(device, deviceInfoData);
            SaasSpaceDeviceRelation relation = relationMap.get(device.getDeviceName());
            if (relation != null){
                deviceInfoData.setSpaceInfoId(relation.getSpaceInfoId());
            }
            Map<String, Object> deviceAttributes = rexolarApiClient.getDeviceAttributes(deviceInfoData.getCoreId(),
                    token, new String[]{Constants.ACTIVE, Constants.LAST_CONNECT_TIME});
            if (!CollectionUtils.isEmpty(deviceAttributes)){
                boolean active = deviceAttributes.get(Constants.ACTIVE) != null && (Boolean) deviceAttributes.get(Constants.ACTIVE);
                deviceInfoData.setStatus(active? 1:0);
                deviceInfoData.setLastUpdateTime(deviceAttributes.get(Constants.LAST_CONNECT_TIME) != null?
                        (Long) deviceAttributes.get(Constants.LAST_CONNECT_TIME):0L);

            }
            result.add(deviceInfoData);
        }
        return result;
    }

    public Boolean reset(String deviceName, String token) {
        DeviceBasicData deviceBasicData = rexolarApiClient.getDeviceByDeviceName(deviceName, token);
        if (deviceBasicData == null){
            log.error("reset deviceBasicData is null, deviceName:{}", deviceName);
            return false;
        }
        HashMap<String,  Object> dataMap = new HashMap();
        dataMap.put(Constants.Version, "1.0");
        dataMap.put("VendorCode", "Rexense");
        String time = String.valueOf(System.currentTimeMillis());
        dataMap.put("Timestamp", time);
        dataMap.put("Seq", deviceName + "-" + time);
        dataMap.put("deviceId", deviceBasicData.getName());
        dataMap.put("FunctionCode", "InvokeCmd");
        JSONObject payload = new JSONObject();
        payload.put("FactoryReset", new JSONObject());
        dataMap.put("Payload", payload);
        boolean flag =  rexolarApiClient.updateDeviceAttributes(deviceBasicData.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
        if(!flag){
            log.error("reset error, deviceName:{}", deviceName);
            return false;
        }
        saasSpaceDeviceRelationMapper.delete(new LambdaQueryWrapper<SaasSpaceDeviceRelation>().eq(SaasSpaceDeviceRelation::getDeviceName, deviceName));
        saasDeviceLabelRelationMapper.delete(new LambdaQueryWrapper<SaasDeviceLabelRelation>().eq(SaasDeviceLabelRelation::getDeviceName, deviceName));
        List<SaasDeviceInfo> list = saasDeviceInfoMapper.selectList(new LambdaQueryWrapper<SaasDeviceInfo>().eq(SaasDeviceInfo::getDeviceName, deviceName));
        if (!CollectionUtils.isEmpty(list)){
            SaasDeviceInfo deviceInfo = list.get(0);
            flag = deleteCustomerDevice(deviceInfo, token);
            if (!flag){
                log.error("reset deleteCustomerDevice error, deviceName:{}", deviceName);
                return false;
            }
        }
        return true;
    }

    public List<SaasSpaceDevicePosition> getDeviceByPosition(Long spaceInfoId, String tenantId) {
        LambdaQueryWrapper<SaasSpaceDevicePosition> queryWrapper = new LambdaQueryWrapper<SaasSpaceDevicePosition>();
        if (spaceInfoId != null){
            queryWrapper.eq(SaasSpaceDevicePosition::getSpaceInfoId, spaceInfoId);
        }
        queryWrapper.eq(SaasSpaceDevicePosition::getTenantId, tenantId);
        return saasSpaceDevicePositionMapper.selectList(queryWrapper);
    }

    public boolean setPosition(DeviceSetPositionRequest deviceSetPositionRequest, String token) {
        List<SaasSpaceDevicePosition> positions = saasSpaceDevicePositionMapper.selectList(new LambdaQueryWrapper<SaasSpaceDevicePosition>()
                .eq(SaasSpaceDevicePosition::getDeviceName, deviceSetPositionRequest.getDeviceName())
                .eq(SaasSpaceDevicePosition::getTenantId, JwtUtils.getTenantId(token))
                .eq(SaasSpaceDevicePosition::getSpaceInfoId, deviceSetPositionRequest.getSpaceInfoId())
                .eq(SaasSpaceDevicePosition::getRouter, deviceSetPositionRequest.getRouter())
        );
        if (!CollectionUtils.isEmpty(positions)){
            SaasSpaceDevicePosition position = positions.get(0);
            position.setPosition(deviceSetPositionRequest.getPosition());
            position.setCustomerId(JwtUtils.getCustomerId(token));
            position.setGmtModified(new Date());
            return saasSpaceDevicePositionMapper.updateById(position) > 0;
        }else {
            SaasSpaceDevicePosition position = new SaasSpaceDevicePosition();
            position.setDeviceName(deviceSetPositionRequest.getDeviceName());
            position.setTenantId(JwtUtils.getTenantId(token));
            position.setSpaceInfoId(deviceSetPositionRequest.getSpaceInfoId());
            position.setRouter(deviceSetPositionRequest.getRouter());
            position.setPosition(deviceSetPositionRequest.getPosition());
            position.setTenantId(JwtUtils.getTenantId(token));
            position.setCustomerId(JwtUtils.getCustomerId(token));
            position.setGmtModified(new Date());
            position.setGmtCreated(new Date());
            return saasSpaceDevicePositionMapper.insert(position) > 0;
        }
    }

    public List<SaasDeviceInfo> getDeviceByAlias(String room, String tenantId) {
        return saasDeviceInfoMapper.selectList(new LambdaQueryWrapper<SaasDeviceInfo>().eq(SaasDeviceInfo::getDeviceAlias, room).eq(SaasDeviceInfo::getTenantId, tenantId));
    }

    public List<SaasSpaceDeviceRelation> getSpaceDeviceRelations(Long spaceInfoId, String tenantId) {
        LambdaQueryWrapper<SaasSpaceDeviceRelation> queryWrapper = new LambdaQueryWrapper<SaasSpaceDeviceRelation>();
        if (spaceInfoId != null){
            queryWrapper.eq(SaasSpaceDeviceRelation::getSpaceInfoId, spaceInfoId);
        }
        queryWrapper.eq(SaasSpaceDeviceRelation::getTenantId, tenantId);
        return saasSpaceDeviceRelationMapper.selectList(queryWrapper);
    }

    public List<SaasSpaceDevicePosition> getDevicePositionByName(List<String> deviceNameList, String tenantId) {
        LambdaQueryWrapper<SaasSpaceDevicePosition> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SaasSpaceDevicePosition::getDeviceName, deviceNameList);
        queryWrapper.eq(SaasSpaceDevicePosition::getTenantId, tenantId);
        return saasSpaceDevicePositionMapper.selectList(queryWrapper);
    }
}

